package com.aquarium.sensor;

import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;

import com.aquarium.R;
import com.aquarium.alarm.AlarmManager;
import com.aquarium.bt.BTManager;
import com.aquarium.bt.DataInterpreter;
import com.aquarium.bt.DataStruct;
import com.aquarium.config.BTCommand;
//import com.aquarium.bt.RecvDataDispatcher;
import com.aquarium.history.HistoryManager;
import com.aquarium.ui.SensorValueDisplayActivity;

public class SensorManager extends Observable implements Observer {
	private static final String TAG = "SensorManager";

	public final static String PH_VALUE_KEY = "PH_VALUE_KEY";
	public final static String TEMPERATURE_VALUE_KEY = "TEMPERATURE_VALUE_KEY";
	public final static String OXYGEN_VALUE_KEY = "OXYGEN_VALUE_KEY";
	public final static String CONDUCTIVITY_VALUE_KEY = "CONDUCTIVITY_VALUE_KEY";
	public final static String WATER_LEVEL_VALUE_KEY = "WATER_LEVEL_VALUE_KEY";

	public final static int HANDLE_PH_VALUE = 0;
	public final static int HANDLE_TEMPERATURE_VALUE = 1;
	public final static int HANDLE_OXYGEN_VALUE = 2;
	public final static int HANDLE_CONDUCTIVITY_VALUE = 3;
	public final static int HANDLE_WATER_LEVEL_VALUE = 4;

	private static SensorManager mSensorManager;
	// private RecvDataDispatcher mRecvDataDispatcher;

	private float mCurrentPhValue;
	private float mCurrentTemperatureValue;
	private float mCurrentOxygenValue;
	private float mCurrentConductivityValue;
	private float mCurrentWaterLevelValue;
	private HashMap<String, String> mSensorValueMap;

	// test code
	private Timer mNotifySensorValueTimer;
	private BTManager mBtManager;
	private DataInterpreter mDataInterpreter;

	private boolean bRefreshingValue = false;

	private boolean bGetPh = false;
	private boolean bGetTemp = false;
	private boolean bGetOxygen = false;
	private boolean bGetConductivty = false;
	private boolean bGetWaterLevel = false;

	private Handler mUiHandler;

	private SensorManager() {
		mSensorValueMap = new HashMap<String, String>();
		// mRecvDataDispatcher = RecvDataDispatcher.getInstance();
		// mRecvDataDispatcher.setSensorValueHandler(mSensorValueHandler);
		mBtManager = BTManager.getInstance();
		mBtManager.addObserver(this);
		mDataInterpreter = new DataInterpreter();
	}

	/**
	 * {@link RecvDataDispatcher} will use this handler to send sensor value
	 * data to {@link Handler#handleMessage(Message)}
	 */
	private Handler mSensorValueHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case HANDLE_PH_VALUE:
				if (msg.obj instanceof byte[]) {
					mCurrentPhValue = Float
							.valueOf(new String((byte[]) msg.obj));
				}
				break;
			case HANDLE_TEMPERATURE_VALUE:
				if (msg.obj instanceof byte[]) {
					mCurrentTemperatureValue = Float.valueOf(new String(
							(byte[]) msg.obj));
				}
				break;
			case HANDLE_OXYGEN_VALUE:
				if (msg.obj instanceof byte[]) {
					mCurrentOxygenValue = Float.valueOf(new String(
							(byte[]) msg.obj));
				}
				break;
			case HANDLE_CONDUCTIVITY_VALUE:
				if (msg.obj instanceof byte[]) {
					mCurrentConductivityValue = Float.valueOf(new String(
							(byte[]) msg.obj));
				}
				break;
			case HANDLE_WATER_LEVEL_VALUE:
				if (msg.obj instanceof byte[]) {
					mCurrentWaterLevelValue = Float.valueOf(new String(
							(byte[]) msg.obj));
				}
				break;

			default:
				break;
			}
		};
	};

	public static SensorManager getInstance() {
		if (mSensorManager == null) {
			mSensorManager = new SensorManager();
		}
		return mSensorManager;
	}

	/**
	 * 获取ph值
	 * 
	 * @return ph值
	 */
	public float getPhValue() {
		// TODO
		return 0;
	}

	/**
	 * 获取水温值
	 * 
	 * @return 水温值
	 */
	public float getTemperature() {
		// TODO
		return 0;
	}

	/**
	 * 获取含氧量
	 * 
	 * @return 含氧量
	 */
	public float getOxygenLevel() {
		// TODO
		return 0;
	}

	/**
	 * 获取咸度（导电率）
	 * 
	 * @return 导电率
	 */
	public float getConductivity() {
		// TODO
		return 0;
	}

	/**
	 * 獲取水位
	 * 
	 * @return 水位
	 */
	public float getWaterLevel() {
		// TODO
		return 0;
	}

	public void setUiHandler(Handler handler) {
		this.mUiHandler = handler;
	}

	/**
	 * Notify and send current sensor value to observers, such as
	 * {@link SensorValueDisplayActivity}, {@link AlarmManager} and
	 * {@link HistoryManager}
	 */
	public void notifySensorValueChanged() {
		mSensorValueMap.clear();
		mSensorValueMap.put(PH_VALUE_KEY, String.valueOf(mCurrentPhValue));
		mSensorValueMap.put(TEMPERATURE_VALUE_KEY,
				String.valueOf(mCurrentTemperatureValue));
		mSensorValueMap.put(OXYGEN_VALUE_KEY,
				String.valueOf(mCurrentOxygenValue));
		mSensorValueMap.put(CONDUCTIVITY_VALUE_KEY,
				String.valueOf(mCurrentConductivityValue));
		mSensorValueMap.put(WATER_LEVEL_VALUE_KEY,
				String.valueOf(mCurrentWaterLevelValue));

		setChanged();
		notifyObservers(mSensorValueMap);
	}

	/**
	 * flush and get latest sensor value from remote BT device
	 * 
	 */
	public void refreshSensorValue() {
		setGetValueState(false);
		bRefreshingValue = true;
		Log.e(TAG, "refreshSensorValue: bRefreshingValue --> true");
		
		// 此处每发送一条command，后面的update都会相应执行
		mBtManager.sendData(DataInterpreter.unpack(new byte[] { 0x5A, 0x01,
				0x68, 0x01, 0x00 }));
		SystemClock.sleep(100);
		mBtManager.sendData(DataInterpreter.unpack(new byte[] { 0x5A, 0x01,
				0x69, 0x01, 0x00 }));
		SystemClock.sleep(100);
		mBtManager.sendData(DataInterpreter.unpack(new byte[] { 0x5A, 0x01,
				0x6A, 0x01, 0x00 }));
		SystemClock.sleep(100);
		mBtManager.sendData(DataInterpreter.unpack(new byte[] { 0x5A, 0x01,
				0x6B, 0x01, 0x00 }));
		SystemClock.sleep(100);
		mBtManager.sendData(DataInterpreter.unpack(new byte[] { 0x5A, 0x01,
				0x6C, 0x01, 0x00 }));
	}

	public void cancelRefreshSensorValue() {
		bRefreshingValue = false;
		Log.e(TAG, "cancelRebRefreshingValue --> false");
		setGetValueState(false);
	}

	private void setGetValueState(boolean state) {
		bGetPh = false;
		bGetTemp = false;
		bGetOxygen = false;
		bGetConductivty = false;
		bGetWaterLevel = false;
	}

	public HashMap<String, String> getSensorValueMap() {
		return mSensorValueMap;
	}

	/**
	 * test code
	 */
	// public void notifySensorValueTest() {
	// if (mNotifySensorValueTimer != null) {
	// mNotifySensorValueTimer.cancel();
	// }
	// mNotifySensorValueTimer = new Timer();
	// mNotifySensorValueTimer.schedule(new TimerTask() {
	//
	// @Override
	// public void run() {
	// notifySensorValueChanged();
	// }
	// }, 800, 5000);
	//
	// }

	/**
	 * test code
	 */
	// public void stopNotifySensorValueTest() {
	// if (mNotifySensorValueTimer == null) {
	// return;
	// }
	// mNotifySensorValueTimer.cancel();
	// }

	@Override
	public void update(Observable observable, Object data) {
		if (observable instanceof BTManager) {
			final DataStruct receivedData = (DataStruct) data;
			// byte[] resposeData = DataInterpreter.pack(receivedData);

			// for (int i = 0; i < receivedData.length; i++) {
			Log.e(TAG, "data:" + Integer.toHexString(receivedData.code & 0xFF));
			// }
			if (receivedData.prefix == 0x5a && receivedData.id == 0x01) {
				switch (receivedData.code) {
				case BTCommand.CODE_GET_PH_VALUE:
					mCurrentPhValue = DataInterpreter
							.unpackPhData(receivedData.data);
					bGetPh = true;
					break;
				case BTCommand.CODE_GET_TEMPERATURE_VALUE:
					mCurrentTemperatureValue = DataInterpreter
							.unpackTemperatureData(receivedData.data);
					bGetTemp = true;
					break;
				case BTCommand.CODE_GET_OXYGEN_VALUE:
					mCurrentOxygenValue = DataInterpreter
							.unpackOxygenData(receivedData.data);
					bGetOxygen = true;
					break;
				case BTCommand.CODE_GET_CONDUCTIVITY_VALUE:
					mCurrentConductivityValue = DataInterpreter
							.unpackConductivityData(receivedData.data);
					bGetConductivty = true;
					break;
				case BTCommand.CODE_GET_WATER_LEVEL_VALUE:
					mCurrentWaterLevelValue = DataInterpreter
							.unpackWaterLevelData(receivedData.data);
					bGetWaterLevel = true;
					break;

				default:
					break;
				}
				notifySensorValueChanged();
				if (bRefreshingValue) {
					if (bGetWaterLevel && bGetConductivty && bGetOxygen
							&& bGetTemp && bGetPh) {
						bRefreshingValue = false;
						Log.e(TAG, "bRefreshingValue --> false");
						Log.e(TAG, "send message: get sensor value success.");
						mUiHandler
								.sendEmptyMessage(SensorValueDisplayActivity.HANLE_REQUST_SENSOR_VALUE_SUCCESS);
					}
				}
			}
		}
	}
}
